package br.com.gentech.commons.model.repository;

import java.io.File;
import java.sql.SQLException;

import org.apache.log4j.Logger;
import org.dbunit.JndiBasedDBTestCase;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.DefaultDataSet;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.dbunit.operation.DeleteOperation;

/**
 * TestCase usado para iteragir com a base de dados.
 * 
 * @author Cindy Soares
 *
 */
public class DBUnitRunner extends JndiBasedDBTestCase {
	
	private static final Logger log = Logger.getLogger(DBUnitRunner.class);

	private static final String DATASET_EXTENSION = ".xml";

	private FlatXmlDataSet dataset;
	private QueryDataSet datasetTearDown;
	
	private String testClassName;
	private String jndiDataSourceName;
	
	public DBUnitRunner(String testName, String testClassName, String jndiDataSourceName) {
		super(testName);
		this.testClassName = testClassName;
		this.jndiDataSourceName = jndiDataSourceName;
	}
	@Override
	protected String getLookupName() {
		return jndiDataSourceName;
	}
/*
	@Override
	protected void setUpDatabaseConfig(DatabaseConfig config){
		config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new PostgresqlDataTypeFactory());
	}
*/
	protected DatabaseOperation getSetUpOperation() throws Exception {
		return DatabaseOperation.INSERT;
	}

	protected DatabaseOperation getTearDownOperation() throws Exception {
		return DatabaseOperation.DELETE;
	}

	@Override
	protected IDataSet getDataSet() throws Exception {
		if(dataset==null) {
			String classesPath = this.getClass().getResource("/").toURI().getPath();
			
			int indexSimpleName = testClassName.lastIndexOf(".");
			String testClassSimpleName = testClassName.substring(indexSimpleName+1);
			String testClassPath = testClassName.substring(0, indexSimpleName).replace('.', File.separator.charAt(0));
			
			File diretorioXml = new File(classesPath + testClassPath + File.separator 
					+ testClassSimpleName.substring(0, 1).toLowerCase() 
					+ testClassSimpleName.substring(1));

			String nomeXml = this.getName() + DATASET_EXTENSION;
			File xml = new File(diretorioXml, nomeXml);
			if(!xml.exists()) {
				log.warn("Dataset do teste \"" + this.getName() + "\" não existe.");
				return new DefaultDataSet();
			}

			dataset = new FlatXmlDataSet(xml, false);
		}
		return dataset;
	}

	@Override
	public void setUp() throws Exception {
		dataset = null;
		datasetTearDown = new QueryDataSet(getConnection());
		super.setUp();
	}

	@Override
	public void tearDown() throws Exception {
		DeleteOperation delete = (DeleteOperation) DatabaseOperation.DELETE;
		delete.execute(getConnection(), datasetTearDown);
		super.tearDown();
	}
	
	/**
	 * 
	 * @param tableName
	 * @param sql
	 * @return
	 * @throws SQLException
	 * @throws Exception
	 */
	public ITable createTable(String tableName, String sql) throws SQLException, Exception {
		return createTable(tableName, sql, false);
	}

	/**
	 * 
	 * @param tableName
	 * @param sql
	 * @param deleteRowsOnTearDown
	 * @return
	 * @throws SQLException
	 * @throws Exception
	 */
	public ITable createTable(String tableName, String sql, boolean deleteRowsOnTearDown) throws SQLException, Exception {
		if(deleteRowsOnTearDown) {
			datasetTearDown.addTable(tableName, sql);
		} 
		ITable table = getConnection().createQueryTable(tableName, sql);
		return table;
	}
}
